/* Copyright 2010 Hugh Greenberg */   

//Based of Tutorial from: http://insanitydesign.com/wp/projects/nehe-android-ports/
package com.hugegreenbug.msoss;

import java.nio.ByteBuffer;
import java.nio.ByteOrder;
import java.nio.FloatBuffer;

import javax.microedition.khronos.opengles.GL10;

import android.util.Log;

public class Wall {
	private FloatBuffer vertexBuf;
	private FloatBuffer texBuf;
	private ByteBuffer indexBuf;
	private int[] textures = new int[1];
	private boolean mTextureSet = false;
	private FloatBuffer normBuf;
	private boolean mWall;
	private int mMode;
	private Background mBg;
	
	private float vertices[] = {
			//Front Face
			-1.0f, -1.0f, 1.0f,
			1.0f, -1.0f, 1.0f,
			-1.0f, 1.0f, 1.0f,
			1.0f, 1.0f, 1.0f,
	};
	
	private float[] texcoords  = {
			//Front Face
			0.0f, 0.0f,
    		1.0f, 0.0f,
    		0.0f, 1.0f,
    		1.0f, 1.0f, 
	};
	
	private float normals[] = {
			//Front Face
			0.0f, 0.0f, 4.0f, 						
			0.0f, 0.0f, 4.0f, 
			0.0f, 0.0f, 4.0f, 
			0.0f, 0.0f, 4.0f, 
	};

	
	private byte[] indicies = {
			0, 1, 3,    0, 3, 2,       //Front Face
	};
	
	public Wall() {
		ByteBuffer buf = ByteBuffer.allocateDirect(vertices.length * 4);
		buf.order(ByteOrder.nativeOrder());
		vertexBuf = buf.asFloatBuffer();
		vertexBuf.put(vertices);
		vertexBuf.position(0);
		
		buf = ByteBuffer.allocateDirect(texcoords.length * 4);
		buf.order(ByteOrder.nativeOrder());
		texBuf = buf.asFloatBuffer();
		texBuf.put(texcoords);
		texBuf.position(0);
		
		buf = ByteBuffer.allocateDirect(indicies.length);
		buf.order(ByteOrder.nativeOrder());
		indexBuf = buf;
		indexBuf.put(indicies);
		indexBuf.position(0);
		
		buf = ByteBuffer.allocateDirect(normals.length * 4);
		buf.order(ByteOrder.nativeOrder());
		normBuf = buf.asFloatBuffer();
		normBuf.put(normals);
		normBuf.position(0);
		
		textures[0] = -1;
		mWall = false;
		mMode = 0;
		mBg = null;
	}
	
	public void init(GL10 gl) {
		if (textures[0] < 0)
			gl.glGenTextures(1, textures, 0);
	}
	
	public void draw(GL10 gl, float alpha) {
		if (!mTextureSet)
			return;
		
		try {
			gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
			gl.glEnableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glEnableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
			gl.glEnableClientState(GL10.GL_NORMAL_ARRAY);
			gl.glFrontFace(GL10.GL_CCW);
			gl.glVertexPointer(3, GL10.GL_FLOAT, 0, vertexBuf);
			gl.glTexCoordPointer(2, GL10.GL_FLOAT, 0, texBuf);
			gl.glNormalPointer(GL10.GL_FLOAT, 0, normBuf);
			
			if (mWall && alpha < 1.0f) {		
				gl.glEnable(GL10.GL_BLEND );
				gl.glBlendFunc(GL10.GL_SRC_ALPHA, GL10.GL_ONE_MINUS_SRC_ALPHA);
				gl.glColor4f(1.0f, 1.0f, 1.0f, alpha);
			} else {
				gl.glDisable(GL10.GL_BLEND );
				gl.glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
			}

			gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
			gl.glDrawElements(GL10.GL_TRIANGLES, indicies.length, GL10.GL_UNSIGNED_BYTE, indexBuf);
			gl.glDisableClientState(GL10.GL_VERTEX_ARRAY);
			gl.glDisableClientState(GL10.GL_TEXTURE_COORD_ARRAY);
			gl.glDisableClientState(GL10.GL_NORMAL_ARRAY);

		} catch (Exception e) {
			Log.e("Musician Slideshow", "Error while drawing wallpaper texture");
		}
	}
	
	public void setTexture(GL10 gl, Background bg, int width, int height, boolean wall, 
			boolean zoom, boolean stretch) {
		if (mTextureSet) 
			return;
		
		if (bg == null || bg.getByteBuffer() == null)
			return;
		
		mBg = bg;
		if (wall)
			mWall = wall;
		
		if (zoom) {
			mMode = MsRenderer.ZOOM_MODE;
		} else if (stretch) { 
			mMode = MsRenderer.STRETCH_MODE;
		} else {
			mMode = MsRenderer.CUBE_MODE;
		}

		init(gl);
		setSize(width, height);
		gl.glBindTexture(GL10.GL_TEXTURE_2D, textures[0]);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MIN_FILTER, GL10.GL_NEAREST);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_MAG_FILTER, GL10.GL_LINEAR);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_S, GL10.GL_CLAMP_TO_EDGE);
		gl.glTexParameterf(GL10.GL_TEXTURE_2D, GL10.GL_TEXTURE_WRAP_T, GL10.GL_CLAMP_TO_EDGE);
		gl.glTexEnvf(GL10.GL_TEXTURE_ENV, GL10.GL_TEXTURE_ENV_MODE, GL10.GL_MODULATE);
		gl.glTexImage2D(GL10.GL_TEXTURE_2D, 0, GL10.GL_RGBA, bg.getTexWidth(), bg.getTexHeight(),
			0, GL10.GL_RGBA, GL10.GL_UNSIGNED_BYTE, bg.getByteBuffer());
		mTextureSet = true;
	}
	
	public void setSize(int width, int height) {
		if (textures[0] < 0 || mBg == null)
			return;
		
		float wscale = 1.0f;
		float hscale = 1.0f;
		try {
			if (mMode == MsRenderer.ZOOM_MODE) {
				wscale = Math.round(((float) ((float) mBg.getScaledWidth() * mBg.getZoomScale())/width) * 1000);
				hscale = Math.round(((float) ((float) mBg.getScaledHeight() * mBg.getZoomScale())/height) * 1000);
			} else if (mMode == MsRenderer.STRETCH_MODE) {
				wscale = Math.round(((float) ((float) mBg.getScaledWidth() * mBg.getStretchScale())/width) * 1000);
				hscale = Math.round(((float) ((float) mBg.getScaledHeight() * mBg.getStretchScale())/height) * 1000);					
			} else {
				wscale = Math.round(((float) mBg.getScaledWidth()/width) * 1000);
				hscale = Math.round(((float) mBg.getScaledHeight()/height) * 1000);
			}

			wscale /= 1000;
			hscale /= 1000;

		} catch (ArithmeticException ae) {
			wscale = 1.0f;
			hscale = 1.0f;
		}
		
		vertices[0] = -wscale;
		vertices[1] = -hscale;
		vertices[3] = wscale;
		vertices[4] = -hscale;
		vertices[6] = -wscale;
		vertices[7] = hscale;
		vertices[9] = wscale;
		vertices[10] = hscale;
		
		vertexBuf.clear();
		vertexBuf.put(vertices);
		vertexBuf.position(0);
	}
	public void releaseTextures(GL10 gl) {
		if (textures[0] > 0) {
			gl.glDeleteTextures(1, textures, 0);
			textures[0] = -1;
		}
		
		mBg = null;
		mTextureSet = false;
	}
}
